package ml.tewas.generator;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import javax.imageio.ImageIO;

import ml.tewas.commondata.BoardCell;
import ml.tewas.commondata.ForceStruct;
import ml.tewas.commondata.ThreatClassificationEnum;
import ml.tewas.commondata.ThreatOrientationEnum;
import ml.tewas.commondata.ThreatStruct;
import ml.tewas.gui.DrawingCanvas;
import ml.tewas.util.Utilities;

public class ThreatGenerator {

	private static final int MAX_SPEED = 1;

	private static final String IMAGE_ROOT = "/ml/tewas/images/";

	private Random randomNumberGenerator;

	private List<BoardCell> previousPositions = new ArrayList<BoardCell>();

	public ThreatGenerator() {
		randomNumberGenerator = new Random();
	}

	public List<ThreatStruct> generateThreats(int numberOfThreats) {

		List<ThreatStruct> threatList = new ArrayList<ThreatStruct>();

		for (int i = 0; i < numberOfThreats; i++) {
			int speed = getSpeed();
			BoardCell position = getPosition();
			ThreatOrientationEnum orientation = getOrientation(position);
			BufferedImage image = getImage(orientation);
			ThreatStruct temp = new ThreatStruct(i,speed, position, orientation,
					image);
			Map<Integer, ThreatClassificationEnum> classifications = getClassifications(temp);
			temp.setClassifications(classifications);
			temp.setAgentsPositions(getAgentsPositions());
			
			threatList.add(temp);
		}
		return threatList;
	}

	private List<BoardCell> getAgentsPositions() {
		DrawingCanvas instance = DrawingCanvas.getInstance();
		List<BoardCell> list = new ArrayList<BoardCell>();
		for(ForceStruct agent : instance.getForceList()){
			list.add(agent.getPosition());
		}
		return list;
	}

	private int getSpeed() {
		return randomNumberGenerator.nextInt(MAX_SPEED) + 1;
	}

	private ThreatOrientationEnum getOrientation(BoardCell position) {

		int sector = getSector(position);
		int orientation = 0;
		switch (sector) {
		case 0:
			orientation = randomNumberGenerator.nextInt(5) + 3;
			break;
		case 1:
			orientation = (randomNumberGenerator.nextInt(5) + 5) % 8;
			break;
		case 2:
			orientation = (randomNumberGenerator.nextInt(5) + 7) % 8;
			break;
		case 3:
			orientation = randomNumberGenerator.nextInt(5) + 1;
			break;
		default:
			break;
		}
		return ThreatOrientationEnum.values()[orientation];
	}

	private int getSector(BoardCell position) {

		int x = position.getCellXPosition();
		int y = position.getCellYPosition();
		if (x > 7 && y < 8)
			return 0;
		else if (x > 7 && y > 7)
			return 1;
		if (x < 8 && y > 7)
			return 2;
		else
			return 3;
	}

	private Map<Integer, ThreatClassificationEnum> getClassifications(ThreatStruct threat) {
		
		Map<Integer, ThreatClassificationEnum> classifications = new HashMap<Integer, ThreatClassificationEnum>();
		List<BoardCell> path = getThreatPath(threat);
		DrawingCanvas instance = DrawingCanvas.getInstance();
		for(ForceStruct agent : instance.getForceList()){
			classifications.put(agent.getAgentID(), Utilities.getClassification(agent.getPosition(), path));
		}
		return classifications;
	}

	private List<BoardCell> getThreatPath(ThreatStruct threat) {
	
		List<BoardCell> path = new ArrayList<BoardCell>();
		BoardCell temp = new BoardCell(threat.getPosition());
		int constantspeed = 1; //it should be one
		while(Utilities.checkPosition(temp)){
			path.add(new BoardCell(temp));
			Utilities.updatePosition(temp, constantspeed, threat.getOrientation());
		}
		return path;
	}

	private BoardCell getPosition() {
		int x;
		int y;
		while (true) {
			x = randomNumberGenerator.nextInt(16);
			y = randomNumberGenerator.nextInt(16);
			if (!Utilities.inSafeZone(x, y)) {
				BoardCell temp = new BoardCell(x, y);
				if (!previouslyTaken(x, y)) {
					previousPositions.add(temp);
					return temp;
				}
			}
		}
	}

	private boolean previouslyTaken(int x, int y) {

		for (BoardCell temp : previousPositions) {
			if (temp.getCellXPosition() == x && temp.getCellYPosition() == y)
				return true;
		}
		return false;
	}

	

	private BufferedImage getImage(ThreatOrientationEnum orientation) {
		String path = IMAGE_ROOT + orientation.name() + ".jpg";
		URL imgURL = getClass().getResource(path);
		BufferedImage img = null;
		try {
			img = ImageIO.read(imgURL);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return img;
	}
}
